home *** CD-ROM | disk | FTP | other *** search
- Path: seismo!uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v10i005: Crypt Breaker's Workbench, Part05/11
- Message-ID: <387@uunet.UU.NET>
- Date: 19 Jun 87 03:06:10 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 1998
- Approved: rs@uunet.uu.net
-
- Submitted by: Robert W. Baldwin <BALDWIN@XX.LCS.MIT.EDU>
- Mod.sources: Volume 10, Issue 5
- Archive-name: cbw/Part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 11)."
- # Contents: Read.me cipher.c eclass.c knit.c zeecode.perm
- # Wrapped by rs@uunet on Wed Jun 17 18:17:17 1987
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f Read.me -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Read.me\"
- else
- echo shar: Extracting \"Read.me\" \(9793 characters\)
- sed "s/^X//" >Read.me <<'END_OF_Read.me'
- X
- XUNPACKING NOTES [by Rich $alz]
- X There Usenet distribution of CBW includes six files that have
- Xbeen UUENCODE'd because they contain non-printing characters:
- X UU.foo UU.graphics UU.test UU.test1 UU.test2 UU.test3
- XYou must first decode these files before using them; one of
- Xthe command sets will do the trick:
- X for I in UU.* ; do uudecode $I ; done -- /bin/sh
- X foreach I (UU.*) -- C shell
- X uudecode $I --
- X end --
- X
- X This directory contains the source, documentation, and
- Xauxilary files for the Crypt Breakers Workbench (cbw). CBW is
- Xa multi-window integrated workbench of tools that help a cryptanalist
- Xread files encrypted with the BSD4.2 crypt command. Anyone
- Xmay copy, modify, use, or redistribute this system. It was
- Xoriginally written by Robert W. Baldwin at MIT.
- X
- X
- XGETTING STARTED
- X
- X A user's manual is provided in cbw.doc. The scribe source
- Xfor the user's manual is in cbw.mss. The file Index briefly describes
- Xthe various programs in this directory.
- X
- X CBW is written in C and distributed with the source code to
- Xencourage people to play with it. It should run on any display
- Xterminal. Read the users manual for information on terminal
- Xcompatibility.
- X
- X
- X
- XTO COMPILE CBW
- X
- X Execute "make" with no arguments. CBW uses routines from the termcap
- Xand curses libraries, but it does not use the full curses package.
- X
- X
- XA FEW OTHER NOTES
- X
- X Page 2 of the users manual mentions that CBW cannot work
- X against files that have been run through compress (1) before
- Xencryption. Personally, I would prefer to have a DES-based
- Xself-inverse cipher. Most DES programs need to be told whether they
- Xare in encrypt or decrypt mode. However, IBM only grants free use of
- XDES if it is used according to NBS guidelines, and self-inverse is not
- Xone of the accepted operating modes.
- X
- X
- XTESTING
- X
- X The following is a step by step sequence of commands to exercise
- Xthe Crypt Breakers Workbench. It demonstrates how easily crypt files
- Xcan be broken.
- X
- X 1. Edit stats.slice to set the name of the directory that contains the
- X statistics files. Statistics for scribe documents are included with
- X the source files.
- X
- X The stats.slice file also defines the location of the dictionary
- X used by the lookup-pattern command. The default dictionary is
- X /usr/dict/words. The dictionary is just a list of words, one per
- X line. Case does not matter.
- X
- X 2. Execute 'source stats.slice' to initialize the necessary shell
- X variables.
- X
- X 3. If there is a .slice file for your terminal type (e.g., vt100.slice,
- X or h19.slice), execute source on that file. This initializes the
- X graphics map and key map.
- X
- X 4. Print out cbw.doc, so you can read it after you have decided that
- X you can't figure out how the program works.
- X
- X 5. Copy test3.perm and .cipher to foo.perm and foo.cipher. The .txt
- X files contain the original plaintext.
- X
- X 6. Execute 'cbw foo'.
- X
- X 7. The cursor will on the command line. Use the arrow keys (or C-P,
- X C-N, C-F, C-B) to move the cursor to the upper lefthand position of
- X the decryption window. Try typing '@Device[Dover]'. Notice that
- X most of the characters you type deduced other characters in the
- X block.
- X
- X 8. The 'D' in 'Dover' is wrong. Using the arrow keys, position the
- X cursor over the 'D' and type 'd'.
- X
- X 9. Advance to the position after the ']' and type C-T. A list of
- X possible characters for this position will be displayed. The list
- X is sorted with the most likely character on the left. Notice that
- X many characters are not possible because they would deduce non-ascii
- X characters elsewhere in the block, or they would conflict with
- X previously accepted guesses.
- X
- X Try guessing tab, comma and linefeed for the character after the
- X ']'. Use C-G to undo each guess. Delete and C-D do not restore the
- X old state, they just erase the wiring that was deduced by a
- X particular character.
- X
- X 10. Move the cursor down to the command line. You can use emacs cursor
- X characters (C-N, C-P, C-F, C-B) or the arrow keys. Unfortunately,
- X C-U does not work as in emacs. The C-X key or F4 will jump directly
- X to the command line.
- X
- X 11. Type 'pw '. The space will cause command completion for the
- X probable-word guessing command. Type F2 (or C-S) to advance to the
- X first argument, and enter the file name 'mss.words'. That file
- X contains a list of keywords used by the Scribe (Finalword) text
- X formatter. Press F2 to advance to the second argument, which
- X specifies a cut-off level for automatically accepting guesses. The
- X level is the maximum number of standard deviations that the scoring
- X function can be away from its expected value. Enter 1.2, and press
- X return to invoke the command.
- X
- X 12. A partially filled in block will appear in the guessing window. To
- X accept the result of this command, press F3 (or C-A).
- X
- X 13. Try the pword guess command again with a level of 3. To do this,
- X just move to the command line, change the 1.2 to a 3, and press
- X return. Again F3 accepts the guess. If some guesses look wrong
- X (such as the 'F' on the second line under the '[Article]'), you can
- X correct them using the editor in the decryption block window.
- X
- X 14. Advance to block 1 of the file by moving the cursor to the
- X decryption window and pressing F2 (or C-S). F1 (or C-R) moves back
- X one block, F2 moves ahead one block.
- X
- X 15. The second block is likely to be plain english with few scribe
- X commands. Move to the command window, type C-U to erase the line
- X and type 'bi ' to setup the bigram guessing command. Try an
- X acceptance level of 1.0 and a minimum probability of 0.6. Type
- X return to invoke the command.
- X
- X 16. After a short wait (~15 seconds), a partial block will appear.
- X Accept the guess with the F3 key in the guessing window.
- X
- X 17. Try looking up a pattern in the dictionary. In the command window
- X type 'look ', use F2 to advance to the pattern, and type in the
- X pattern '....llit.', and press return. This will match against the
- X word 'satellite' if it is in you site's dictionary.
- X
- X 18. One could go on like this, but let's skip ahead by loading in a
- X previously saved state. Invoke the load command (it loads the file
- X foo.perm, just as save dumps to foo.perm (making this command take a
- X filename is a good implementation exercise)). Type C-U, 'load ',
- X and return. Notice that all the work so far is replaced by the
- X information in the .perm file. This can be considered a feature.
- X
- X 19. Use the F1 and F2 keys in the decryption window to view the blocks
- X that have been solved. Notice that a fully solved block does not
- X specify all the wirings of the block key (permutation). Typically
- X only 105 of the 128 wires are used.
- X
- X 20. Lets try deducing the inter-block relationship (zee). Execute the
- X clear-zee command.
- X
- X 21. Execute knit blocks 0 through 3 with a min show count of 20. This
- X means that the program should only show you guesses that deduce 20
- X or more wirings of the zee permutation. Press return to invoke this
- X guessing strategy. The cursor will move to the guessing window.
- X Press F2 to start the first round of guessing.
- X
- X The running time of the knit command is exponential in the number of
- X blocks knitted, and it will run for a very long time if any of the
- X blocks are decrypted incorrectly. This means that it is better to
- X leave a position blank than to guess at it.
- X
- X 22. The program moves to block 4 and shows you the characters in block 4
- X that would be deduced from block 3 given the deduced wirings of zee.
- X If these look reasonable, press F3 to accept the guess, and press F2
- X to try the next guess. To reject a guess, press F2 without pressing
- X F3.
- X
- X 23. Now that part of zee is known, try propagating the settings of block
- X 1 into block 0 using zee. The propagate command will do this. Also
- X try propagating blocks 2, 3, and 4 to zero.
- X
- X Notice that the number of known wires can increase without deducing
- X additional characters in the block.
- X
- X 24. There should be a command that propagates information between groups
- X of blocks, but for now you must do this one block at a time. After
- X propagating block 1 - 4 to block zero, and block zero to blocks 1 -
- X 4, et cetera, try the knit command again.
- X
- X 25. Propagate block 4 to 5 to provide a framework to evaluate new
- X guesses.
- X
- X 26. Knit block 0 through 4 with a minimum show level of 2. You may want
- X to skip accepting guesses that do not deduce any characters. Repeat
- X this process with a show level of 1.
- X
- X 27. The program should now know all 256 wirings of zee. Repeat the
- X process of propagating information between blocks until all 128
- X wires of the block zero are known.
- X
- X 28. Save your work with the save-permutations command (on the command
- X line type 'sa ' and press return). This writes the file foo.perm.
- X
- X 29. Exit the program with the quit command.
- X
- X 30. Copy foo.perm to zeecode.perm.
- X
- X 31. Execute 'zeecode < foo.cipher | more '. This program reads CBW's
- X save file to find the permutation for block zero and the Zee
- X permutation that describes how the remaining block keys are
- X generated. Using this information it decodes standard input and
- X writes on standard output.
- X
- X 32. That's all.
- END_OF_Read.me
- if test 9793 -ne `wc -c <Read.me`; then
- echo shar: \"Read.me\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f cipher.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"cipher.c\"
- else
- echo shar: Extracting \"cipher.c\" \(9641 characters\)
- sed "s/^X//" >cipher.c <<'END_OF_cipher.c'
- X/*
- X * Routines for operating on cipher blocks.
- X *
- X * Robert W. Baldwin, January 1985.
- X */
- X
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "window.h"
- X#include "specs.h"
- X#include "cipher.h"
- X
- X
- X#define DEBUG FALSE
- X
- X
- X/* Decode the cblock into pblock using perm.
- X * Return FALSE if find a non-ascii character, else 1.
- X */
- Xdecode(cblock, pblock, perm)
- Xchar cblock[];
- Xint pblock[];
- Xint perm[];
- X{
- Xint iplace; /* Index into ciphertext block. */
- Xint spchar; /* Plaintext char not unshifted. */
- Xint pchar; /* Plaintext char. */
- Xint good; /* Plaintext doesn't have any unacceptable chars in it. */
- X
- Xgood = TRUE;
- Xfor (iplace = 0 ; iplace < BLOCKSIZE ; iplace++) {
- X spchar = perm[(iplace+cblock[iplace])&MODMASK];
- X if (spchar == -1) {
- X pchar = -1;
- X }
- X else {
- X pchar = (spchar-iplace) & MODMASK;
- X if (notascii(pchar)) {
- X good = FALSE;
- X }
- X }
- X pblock[iplace] = pchar;
- X }
- Xreturn(good);
- X}
- X
- X
- X/* Searches for string in block.
- X * Returns position it found that didn't have conflicts, or -1.
- X * If found, it will add to perm all the deduced wirings.
- X * If perm is not initially all -1, search will not accept any
- X * position that conflicts with the initial wirings, nor will
- X * it mutate any of those wirings.
- X */
- Xint search(cipher, perm, initpos, thing)
- Xchar *cipher;
- Xint *perm;
- Xint initpos;
- Xchar *thing; /* NULL terminated string. */
- X{
- X int iplace; /* Current placement of trigram in plaintext block. */
- X int i; /* Index for initializing arrays. */
- X int pchar; /* Plaintext character. */
- X int spchar; /* Plaintext character cyclically shifted by its pos. */
- X int *spstkp;
- X int spstack[BLOCKSIZE];
- X int *scstkp;
- X int scstack[BLOCKSIZE];
- X int scchar; /* Ciphertext character cyclically shifted by its pos. */
- X int offset;
- X int thinglen;
- X char *p;
- X
- X p = thing;
- X for (thinglen = 0 ; *p++ != 0 ; thinglen++) ;
- X
- X for (iplace = initpos ; iplace < BLOCKSIZE-thinglen ; iplace++) {
- X spstkp = spstack;
- X scstkp = scstack;
- X for (offset = 0 ; offset < thinglen ; offset++) {
- X pchar = ((int) thing[offset]);
- X spchar = (pchar + iplace + offset) & MODMASK;
- X scchar = (cipher[iplace + offset] + iplace + offset) & MODMASK;
- X if ((perm[spchar] != -1 || perm[scchar] != -1)
- X && (perm[spchar] != scchar)) {
- X while (spstkp > &spstack[0]) perm[*(--spstkp)] = -1;
- X while (scstkp > &scstack[0]) perm[*(--scstkp)] = -1;
- X goto nextplace;
- X }
- X perm[spchar] = scchar;
- X *spstkp++ = spchar;
- X perm[scchar] = spchar;
- X *scstkp++ = scchar;
- X }
- X return(iplace);
- X nextplace: ;
- X }
- X return(-1);
- X}
- X
- X
- X/* Fill in the pvec with the characters decoded from assuming
- X * that the ciphertext character at position firstpos maps to
- X * the plaintext character firstplain.
- X * Return the number of characters added to pvec not counting
- X * the termination character (NONE) that we always add.
- X * If any of the characers decoded to non-ascii values, then
- X * return ERROR (a negative number).
- X * Also return ERROR if the guess would conflict with the ones already
- X * in eci->perm.
- X */
- Xint decode_class(eci, firstpos, firstplain, pvec)
- Xecinfo *eci;
- Xint firstpos;
- Xint firstplain;
- Xint *pvec;
- X{
- X int x,y;
- X
- X firstpos = MODMASK & firstpos;
- X firstplain = CHARMASK & firstplain;
- X
- X x = eci->scipher[firstpos];
- X y = MODMASK & (firstplain + firstpos);
- X
- X return(decode_wire(eci, x, y, pvec));
- X}
- X
- X
- X/* Fill in the pvec with the characters decoded from assuming
- X * that the permutation for this block maps x to y and vice-versa.
- X * Return the number of characters added to pvec not counting
- X * the termination character (NONE) that we always add (but not if
- X * we return ERROR).
- X * If any of the characers decoded to non-ascii values, then
- X * return ERROR (a negative number).
- X * Also return ERROR if the guess would conflict with the ones already
- X * in eci->perm.
- X * Also return ERROR if x == y.
- X */
- Xint decode_wire(eci, x, y, pvec)
- Xecinfo *eci;
- Xint x;
- Xint y;
- Xint *pvec;
- X{
- X decode_wire_but(eci, x, y, pvec, NONE, NONE);
- X}
- X
- X
- X/* Fill in the pvec with the characters decoded from assuming
- X * that the permutation for this block maps x to y and vice-versa.
- X * Return the number of characters added to pvec not counting
- X * the termination character (NONE) that we always add (but not if
- X * we return ERROR).
- X * If any of the characers decoded to non-ascii values, then
- X * return ERROR (a negative number).
- X * Also return ERROR if the guess would conflict with the ones already
- X * in eci->perm.
- X * Also return ERROR if x == y.
- X * DO NOT include any characters in the postions ranging from
- X * first to last inclusive.
- X */
- Xint decode_wire_but(eci, x, y, pvec, first, last)
- Xecinfo *eci;
- Xint x;
- Xint y;
- Xint *pvec;
- Xint first, last;
- X{
- X int delta;
- X int pos, firstflag;
- X int c,i;
- X int firstpos;
- X int otherpos;
- X int pvecindex;
- X
- X
- X pvecindex = 0;
- X pvec[pvecindex] = NONE;
- X x = x & MODMASK;
- X y = y & MODMASK;
- X if (first > last) {
- X printf("\ndecode_wire_but called with first > last.\n");
- X exit(0);
- X }
- X
- X if (perm_conflict(eci->perm,x,y) || x == y) {
- X#if DEBUG
- X printf("CANNOT accept the guess of %d wired to %d.\n",
- X x, y);
- X#endif
- X return(ERROR);
- X }
- X
- X firstpos = eci->permmap[x];
- X if (firstpos != NONE) {
- X delta = y - x;
- X for_pos_in_class(pos, firstpos) {
- X if (first <= pos && pos <= last) continue;
- X c = MODMASK & (eci->scipher[pos] + delta - pos);
- X if (c != (c & CHARMASK)) return(ERROR);
- X pvec[pvecindex++] = c;
- X }
- X }
- X
- X otherpos = eci->permmap[y];
- X if (otherpos != NONE) {
- X delta = x - y;
- X for_pos_in_class(pos, otherpos) {
- X if (first <= pos && pos <= last) continue;
- X c = MODMASK & (eci->scipher[pos] + delta - pos);
- X if (c != (c & CHARMASK)) return(ERROR);
- X pvec[pvecindex++] = c;
- X }
- X }
- X
- X pvec[pvecindex] = NONE;
- X return(pvecindex);
- X}
- X
- X
- X
- X/* Fill in an interger buffer from the characters of a byte buffer.
- X * The buffers must have equal lengths.
- X */
- Xchar2buf(cptr, iptr, length)
- Xchar *cptr;
- Xint *iptr;
- Xint length;
- X{
- X int i;
- X
- X for (i = 0 ; i < length ; i++) {
- X *iptr++ = MODMASK & (*cptr++);
- X }
- X}
- X
- X
- X/* Fill in a character buffer from the integers of a byte buffer.
- X * If the integer value is NONE, use nonechar instead.
- X * The buffers must have equal lengths.
- X */
- Xbuf2char(cptr, iptr, length, nonechar)
- Xchar *cptr;
- Xint *iptr;
- Xint length;
- Xint nonechar;
- X{
- X int i;
- X
- X for (i = 0 ; i < length ; i++) {
- X if (*iptr != NONE) {
- X *cptr++ = MODMASK & (*iptr++);
- X }
- X else {
- X *cptr++ = nonechar;
- X }
- X }
- X}
- X
- X
- X
- X/* Fill in an interger vector with the characters from a null
- X * terminated string. The interger vector is terminated by the
- X * value NONE.
- X */
- Xstr2pvec(cptr, iptr)
- Xchar *cptr;
- Xint *iptr;
- X{
- X while (*iptr++ = (MODMASK & *cptr++));
- X *(--iptr) = NONE;
- X}
- X
- X
- X/* Fill in a null terminated string with the integers from a NONE
- X * terminated vector.
- X */
- Xpvec2str(cptr, iptr)
- Xchar *cptr;
- Xint *iptr;
- X{
- X while (*iptr != NONE) {
- X *cptr++ = (MODMASK & *iptr++);
- X }
- X *cptr = 0;
- X}
- X
- X
- X/* Print a pvec on a stream.
- X */
- Xprint_pvec(out, pvec)
- XFILE *out;
- Xint *pvec;
- X{
- X int i,c;
- X
- X i = 0;
- X while (*pvec != NONE) {
- X c = *pvec++;
- X if (i++ % 20 == 0) fprintf(out,"\n");
- X write_char(out, c);
- X }
- X fprintf(out,"\n");
- X}
- X
- X
- X/* Returns number of wires added to permvec assuming
- X * that plaintext str occurs at pos.
- X * Fills in permvec. Returns -1 if conflict.
- X * Note that the last entry in permvec is marked by x == -1.
- X * The permvec will not have duplicates and will not conflict
- X * with the perm specified by eci->perm.
- X */
- Xint permvec_from_string(eci, str, pos, permvec)
- Xecinfo *eci;
- Xchar *str;
- Xint pos;
- Xperment permvec[];
- X{
- X int wcount;
- X int i, c, tmp;
- X int x,y;
- X char *cp;
- X int curpos;
- X
- X if (pos < 0 || pos >= BLOCKSIZE) {return(ERROR);}
- X
- X wcount = 0;
- X curpos = pos;
- X cp = str;
- X while ((c = (*cp & MODMASK)) != 0 && (curpos < BLOCKSIZE)) {
- X x = eci->scipher[curpos];
- X y = MODMASK & (c + curpos);
- X if (perm_conflict(eci->perm, x, y)) {
- X permvec[0].x = NONE;
- X return(ERROR);
- X }
- X for (i = 0 ; i < wcount ; i++) {
- X if ( (permvec[i].x == x && permvec[i].y != y)
- X || (permvec[i].x == y && permvec[i].y != x)
- X || (permvec[i].y == x && permvec[i].x != y)
- X || (permvec[i].y == y && permvec[i].x != x) ) {
- X#if DEBUG
- X printf("Conflict within permvec.\n");
- X#endif
- X permvec[0].x = NONE;
- X return(ERROR);
- X }
- X if ( (permvec[i].x == x && permvec[i].y == y)
- X || (permvec[i].x == y && permvec[i].y == x) )
- X break;
- X }
- X permvec[i].x = x;
- X permvec[i].y = y;
- X if (i >= wcount) wcount++;
- X curpos++;
- X cp++;
- X }
- X
- X permvec[wcount].x = NONE;
- X return(wcount);
- X}
- X
- X
- X
- X/* Copy routine for permvecs.
- X */
- Xpermvec_copy(from, to, maxnum)
- Xperment from[];
- Xperment to[];
- Xint maxnum;
- X{
- X int i;
- X
- X for (i = 0 ; i < maxnum ; i++) {
- X to[i] = from[i];
- X if (from[i].x == NONE) break;
- X }
- X}
- X
- X
- X/* Copy routine for pvecs.
- X */
- Xpvec_copy(from, to, maxnum)
- Xint from[];
- Xint to[];
- Xint maxnum;
- X{
- X int i;
- X
- X for (i = 0 ; i < maxnum ; i++) {
- X to[i] = from[i];
- X if (from[i] == NONE) break;
- X }
- X}
- X
- X
- X
- X/* Fills in pvec with the plaintext characters deduced
- X * from the wires in permvec that are not in the positions
- X * ranging from butfirst to butlast. Returns -1 if any
- X * non-ascii chars are deduced, else count of chars.
- X */
- Xint permvec2pvec(eci, permvec, pvec, butfirst, butlast)
- Xecinfo *eci;
- Xperment permvec[];
- Xint pvec[];
- Xint butfirst;
- Xint butlast;
- X{ int i, x, y;
- X int ccount;
- X int added;
- X
- X ccount = 0;
- X
- X for (i = 0 ; permvec[i].x != NONE ; i++) {
- X if (ccount >= BLOCKSIZE-1) break;
- X x = permvec[i].x;
- X y = permvec[i].y;
- X added = decode_wire_but(eci, x, y, &(pvec[ccount]), butfirst, butlast);
- X if (added < 0) {
- X#if DEBUG
- X printf("permvec wire decodes to non-ascii.\n");
- X#endif
- X pvec[0] = -1;
- X return(ERROR);
- X }
- X ccount += added;
- X }
- X pvec[ccount] = -1;
- X return(ccount);
- X}
- END_OF_cipher.c
- if test 9641 -ne `wc -c <cipher.c`; then
- echo shar: \"cipher.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f eclass.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"eclass.c\"
- else
- echo shar: Extracting \"eclass.c\" \(9192 characters\)
- sed "s/^X//" >eclass.c <<'END_OF_eclass.c'
- X/*
- X * Equivalence class information about a cipher block.
- X *
- X * Bob Baldwin, January 1985.
- X */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "window.h"
- X#include "terminal.h"
- X#include "layout.h"
- X#include "specs.h"
- X#include "cipher.h"
- X
- X
- X#define DEBUG FALSE
- X
- X#define MIN_SHOW_SCORE (0.7)
- X#define ECBLABEL1 "Equiv class guessing at level %6.3f -- Please Wait"
- X#define ECBLABEL2 "Equiv class guessing at level %6.3f -- Done"
- X#define ECBHELP "F3 enters guess, ^G undoes it."
- X
- X
- Xextern char mcbuf[];
- Xextern ecinfo gecinfo;
- Xextern ecbdraw(), ecbfirst(), ecbenter(), ecbundo();
- X
- X/* Gloabal State. */
- Xfloat ec_accept_level = 0.0;
- Xkeyer ecbktab[] = {
- X {CACCEPT, ecbenter},
- X {CUNDO, ecbundo},
- X {CGO_UP, jogup},
- X {CGO_DOWN, jogdown},
- X {CGO_LEFT, jogleft},
- X {CGO_RIGHT, jogright},
- X {0, NULL},
- X};
- X
- X
- X/* Routine invoked by user to put up the equivalence class
- X * guessing window.
- X * The window is drawn empty, and then filled in with the guess.
- X * Return NULL if command completes ok.
- X */
- Xchar *ecbguess(str)
- Xchar *str; /* Command line */
- X{
- X ecinfo *ecbi;
- X int i;
- X gwindow *ecb;
- X
- X ecb = &gbstore;
- X ecbi = &gecinfo;
- X ec_init(mcbuf, refperm(dbsgetblk(&dbstore)), ecbi);
- X
- X if ((i = sscanf(str, "%*[^:]: %f", &ec_accept_level)) != 1) {
- X return("Could not parse acceptance level.");
- X }
- X
- X gbsswitch(ecb, ((char *) ecbi), ecbktab, ecbfirst, wl_noop, ecbdraw);
- X
- X sprintf(statmsg, ECBLABEL1, ec_accept_level);
- X gblset(&gblabel, statmsg);
- X
- X ecbdraw(ecb);
- X fflush(stdout);
- X
- X ec_autoguess(ecbi, ec_accept_level);
- X decode(ecbi->ciphertext, ecbi->plaintext, ecbi->perm);
- X
- X sprintf(statmsg, ECBLABEL2, ec_accept_level);
- X gblset(&gblabel, statmsg);
- X ecbdraw(ecb);
- X
- X return(NULL);
- X}
- X
- X
- X/* (re) Draw the window.
- X */
- Xecbdraw(ecb)
- Xgwindow *ecb;
- X{
- X int i;
- X int row, col;
- X ecinfo *ecbi;
- X
- X ecbi = ((ecinfo *) ecb->wprivate);
- X row = 1;
- X col = 1;
- X
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X if (i%LINELEN == 0) {
- X wl_setcur(ecb, gbspos2row(i), gbspos2col(i));
- X }
- X plnchars(1, char2sym(ecbi->plaintext[i]));
- X }
- X
- X for (i = gbspos2row(BLOCKSIZE) ; i <= GBHEIGHT ; i++) {
- X wl_setcur(ecb, i, 1);
- X plnchars(LINELEN, ' ');
- X }
- X
- X for (i = 1 ; i <= GBHEIGHT ; i++) {
- X wl_setcur(ecb, i, LINELEN+1);
- X plnchars(ecb->wwidth - LINELEN, ' ');
- X }
- X
- X wl_setcur(ecb, row, col);
- X}
- X
- X
- X/* First time cursor enters window.
- X */
- Xecbfirst(ecb, row, col)
- Xgwindow *ecb;
- Xint row, col;
- X{
- X usrhelp(&user, ECBHELP);
- X wl_setcur(ecb, row, col);
- X}
- X
- X
- X/* Enter the guess into the decryption block.
- X */
- Xecbenter(ecb)
- Xgwindow *ecb;
- X{
- X ecinfo *ecbi;
- X
- X ecbi = ((ecinfo *) ecb->wprivate);
- X dbsmerge(&dbstore, ecbi->perm);
- X wl_rcursor(ecb);
- X}
- X
- X
- X/* Undo the last guess.
- X */
- Xecbundo(ecb)
- Xgwindow *ecb;
- X{
- X ecinfo *ecbi;
- X
- X ecbi = ((ecinfo *) ecb->wprivate);
- X dbsundo(&dbstore);
- X wl_rcursor(ecb);
- X}
- X
- X
- X
- X
- X/* Dump plaintext chars onto stream.
- X */
- Xec_dplain(out, eci)
- XFILE *out;
- Xecinfo *eci;
- X{
- X int i,c;
- X int *pbuf;
- X
- X pbuf = &eci->plaintext[0];
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X c = *pbuf++;
- X if (i % 20 == 0) fprintf(out,"\n");
- X if (c != NONE)
- X write_char(out, c);
- X else
- X write_char(out, '.');
- X }
- X fprintf(out,"\n");
- X}
- X
- X
- X/* Dump shifted cipher chars onto stream.
- X */
- Xec_dscipher(out, eci)
- XFILE *out;
- Xecinfo *eci;
- X{
- X int i,c;
- X int *pbuf;
- X
- X pbuf = &eci->scipher[0];
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X c = *pbuf++;
- X if (i++ % 20 == 0) fprintf(out,"\n");
- X if (c != NONE)
- X write_char(out, c);
- X else
- X write_char(out, '.');
- X }
- X fprintf(out,"\n");
- X}
- X
- X
- X/* Dump table of next pointers onto a stream.
- X */
- Xec_dnext(out, eci)
- XFILE *out;
- Xecinfo *eci;
- X{
- X writeperm(out, &(eci->next[0]));
- X}
- X
- X
- X/* Dump size table onto a stream.
- X */
- Xec_dsizetab(out, eci)
- XFILE *out;
- Xecinfo *eci;
- X{
- X int i;
- X
- X fprintf(out, "\nThere are %d classes longer than 1 character.\n",
- X eci->sizelast);
- X for (i = 0 ; i < eci->sizelast ; i++) {
- X fprintf(out, "Size: %d, First member: %d.\n",
- X eci->sizelist[i].size, eci->sizelist[i].firstpos);
- X }
- X}
- X
- X
- X/* Dump our permutation onto a stream.
- X */
- Xec_dperm(out, eci)
- XFILE *out;
- Xecinfo *eci;
- X{
- X writeperm(out, &(eci->perm[0]));
- X}
- X
- X
- X/* Dump the permutation map onto a stream.
- X */
- Xec_dpmap(out, eci)
- XFILE *out;
- Xecinfo *eci;
- X{
- X writeperm(out, &(eci->permmap[0]));
- X}
- X
- X
- X
- X/* Update ecbi to reflect the automatic guesses.
- X */
- Xec_autoguess(ecbi, alevel)
- Xecinfo *ecbi;
- Xfloat alevel;
- X{ int i, c;
- X int classpos;
- X int x, y;
- X
- X for (i = 0 ; i < ecbi->sizelast ; i++) {
- X classpos = ecbi->sizelist[i].firstpos;
- X c = ec_best(ecbi, classpos, alevel);
- X if (c != NONE) {
- X x = ecbi->scipher[classpos];
- X y = MODMASK & (c + classpos);
- X if (!perm_conflict(ecbi->perm, x, y)) {
- X ecbi->perm[x] = y;
- X ecbi->perm[y] = x;
- X }
- X#if DEBUG
- X else {
- X printf("ec_autoguess: Best guess conflicts");
- X printf(" with an accepted.\n");
- X }
- X#endif
- X }
- X }
- X}
- X
- X
- X/* Score a single equivalence class.
- X * Bigger scores are better scores. They range from 0 to 1.
- X * A score of zero means the choice is not possible.
- X */
- Xfloat ec_cscore(eci, firstpos, plainchar)
- Xecinfo *eci;
- Xint firstpos;
- Xint plainchar;
- X{
- X extern float logvar;
- X float score;
- X int pvec[BLOCKSIZE+1];
- X int ccount;
- X char str[BLOCKSIZE+1];
- X
- X
- X if (decode_class(eci, firstpos, plainchar, pvec) == ERROR) {
- X return(0.0);
- X }
- X
- X score = pvec_1score(pvec);
- X if (score < 0.0) return(0.0);
- X score = exp(-(score * score) / 2.0);
- X for (ccount = 0 ; pvec[ccount] != NONE ; ccount++);
- X score = score / sqrt(2*PI*logvar/ccount);
- X
- X#if DEBUG
- X if (score > MIN_SHOW_SCORE) {
- X pvec2str(str, pvec);
- X printf("Derived characters are '%s", str);
- X printf("', their score is %7.4f\n", score);
- X }
- X#endif
- X return(score);
- X}
- X
- X
- X/* Select best plaintext value for a ciphertext equiv class.
- X * The class is identified by the position in the block of one
- X * of the characters in the class. The plaintext value for
- X * an entire class can be specified by the plaintext value of
- X * one of its members. This routine returns the best plaintext
- X * value for the ciphertext character at position firstpos.
- X * If there is not a clear best value, NONE is returned.
- X */
- Xint ec_best(eci, firstpos, alevel)
- Xecinfo *eci;
- Xint firstpos;
- Xfloat alevel;
- X{
- X float total_score, score;
- X float best_score;
- X int best_char;
- X int c;
- X int x,y;
- X float count;
- X
- X#if DEBUG
- X int pvec[BLOCKSIZE+1];
- X char str[BLOCKSIZE+1];
- X
- X printf("\n");
- X printf("The first position of this class is %d.\n", firstpos);
- X#endif
- X total_score = 0.0;
- X best_score = 0.0;
- X count = 0.0;
- X best_char = NONE;
- X
- X for (c = 0 ; c <= MAXCHAR ; c++) {
- X score = ec_cscore(eci, firstpos, c);
- X if (score > 0.0) {
- X count += 1.0;
- X total_score += score;
- X }
- X if (score > best_score) {
- X best_score = score;
- X best_char = c;
- X }
- X }
- X
- X#if DEBUG
- X printf("Total score is %7.4f", total_score);
- X printf(". Count is %4.0f.\n", count);
- X#endif
- X if (total_score == 0.0 || count == 0.0 || best_char == NONE) {
- X#if DEBUG
- X printf("NO GUESSES\n");
- X#endif
- X return(NONE);
- X }
- X#if DEBUG
- X printf("Best score is %7.4f", best_score);
- X printf(", which is %7.4f fraction of total", best_score/total_score);
- X printf(".\n");
- X
- X decode_class(eci, firstpos, best_char, pvec);
- X pvec2str(str, pvec);
- X printf("The best chars are '%s.\n", str);
- X#endif
- X
- X if (best_score > alevel * (total_score - best_score)) {
- X return(best_char);
- X }
- X else {
- X return(NONE);
- X }
- X}
- X
- X
- X/* Fill in equiv class info from given ciphertext block
- X * and permutation.
- X */
- Xec_init(cipher, perm, eci)
- Xchar cipher[];
- Xint perm[];
- Xecinfo *eci;
- X{
- X int i,j;
- X int lastmember;
- X int firstpos, size;
- X
- X eci->sizelast = 0;
- X eci->sizemin = 2;
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X eci->ciphertext[i] = cipher[i];
- X eci->scipher[i] = (cipher[i] + i)&MODMASK;
- X eci->perm[i] = perm[i];
- X eci->permmap[i] = NONE;
- X }
- X decode(eci->ciphertext, eci->plaintext, eci->perm);
- X
- X
- X /* The permmap points to the most recent member we have seen */
- X /* of each known class, or a NONE. Ptrs are array indexes. */
- X for (i = BLOCKSIZE-1 ; i >= 0 ; i--) {
- X eci->next[i] = i;
- X if ((lastmember = eci->permmap[eci->scipher[i]]) != NONE) {
- X eci->next[i] = eci->next[lastmember];
- X eci->next[lastmember] = i;
- X }
- X eci->permmap[eci->scipher[i]] = i;
- X }
- X
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X firstpos = eci->permmap[i];
- X if (firstpos != NONE) {
- X size = ec_compsize(eci, firstpos);
- X ec_addsize(eci, size, firstpos);
- X }
- X }
- X}
- X
- X
- X/* Add an entry to the size list.
- X * Implementation: Find the first slot before sizelast+1 that
- X * has a size less than the size arg. Shuffle down the list
- X * to create a hole and insert the new entry.
- X */
- Xec_addsize(eci, size, firstmember)
- Xregister ecinfo *eci;
- Xint size;
- Xint firstmember;
- X{
- X int k; /* Slot where new entry will go. */
- X int i;
- X ecsize sizeinfo;
- X
- X if (size < eci->sizemin) return;
- X
- X sizeinfo.size = size;
- X sizeinfo.firstpos = firstmember;
- X for (k = 0 ; k < eci->sizelast ; k++) {
- X if (eci->sizelist[k].size < size) break;
- X }
- X if (k >= SZMAX) return;
- X
- X for (i = eci->sizelast ; i > k ; i--) {
- X eci->sizelist[i] = eci->sizelist[i-1];
- X }
- X eci->sizelast++;
- X
- X eci->sizelist[k] = sizeinfo;
- X}
- X
- X
- X/* Compute the size of a clas given a pointer to one of its members.
- X */
- Xint ec_compsize(eci, member)
- Xecinfo *eci;
- Xint member;
- X{
- X int size;
- X int position;
- X int firstflag;
- X
- X size = 0;
- X for_pos_in_class(position, member) {
- X size++;
- X }
- X return(size);
- X}
- END_OF_eclass.c
- if test 9192 -ne `wc -c <eclass.c`; then
- echo shar: \"eclass.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f knit.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"knit.c\"
- else
- echo shar: Extracting \"knit.c\" \(10707 characters\)
- sed "s/^X//" >knit.c <<'END_OF_knit.c'
- X/*
- X * Use serveral mostly solved blocks to solve the knitting equation
- X * and deduce the rotor and reflector wirings.
- X *
- X * Robert W. Baldwin, December 1984.
- X */
- X
- X
- X#include <stdio.h>
- X#include "window.h"
- X#include "terminal.h"
- X#include "layout.h"
- X#include "specs.h"
- X
- X
- Xextern char gcbuf[]; /* All guess displays use same buffers. */
- Xextern int gpbuf[];
- Xextern int gperm[];
- X
- X
- X#define KNTHELP "F2 = next guess, F3 = enter guess, ^G = Undo enter."
- X#define STARTMSG "Knitting from %d to %d. Known Zee: %d of 256."
- X#define GUESSMSG "guesscount = %d, xi=%d, yi=%d. Known Zee: %d of 256."
- X#define UNDOMSG "Undone. Current known Zee: %d of 256"
- X#define BIG 1000 /* Size of try stack in kntadvance(). */
- X
- X
- X/* Pack and unpack two bytes into an integer. */
- X#define pack(x,y) (((x&0377)<<8) + y)
- X#define unpack(x,y,v) tmpv = v; x = ((tmpv>>8)&0377); y = (tmpv&0377);
- X
- X
- X/* Keystroke handler table. */
- X
- Xextern int kntadvance();
- Xextern kntundo();
- Xextern kntnextg();
- Xextern kntenter();
- X
- Xkeyer kntktab[] = {
- X {CNEXTGUESS, kntnextg},
- X {CACCEPT, kntenter},
- X {CUNDO, kntundo},
- X {CGO_UP, jogup},
- X {CGO_DOWN, jogdown},
- X {CGO_LEFT, jogleft},
- X {CGO_RIGHT, jogright},
- X {0, NULL},
- X};
- X
- X
- X
- X/* Private data structure for guess blocks. */
- X
- X#define kntinfo struct xkntinfo
- Xstruct xkntinfo {
- X char *cbuf; /* The cipher block. */
- X int *pbuf; /* The derived guess plaintext, -1 = none. */
- X int *perm; /* Permutation of block highbnum+1. */
- X int xindex; /* Starting position of next x guess. */
- X int yindex; /* Starting position of next y guess. */
- X int *zee; /* Knitting matrix. */
- X int *zeeinv; /* Its inverse. */
- X int *ustkp; /* Undo stack pointer. */
- X int *savedustkp; /* Undo stack pointer. */
- X int *undostk; /* Undo stack. */
- X int lowbnum; /* Block number of lowest source. */
- X int highbnum; /* Block number of highest source. */
- X int min_show; /* Smallest count to show. */
- X };
- X
- X
- X/* Private buffers. */
- Xint kzee[BLOCKSIZE+1];
- Xint kzeeinv[BLOCKSIZE+1];
- Xint kustk[BLOCKSIZE+1];
- X
- Xkntinfo kntprivate;
- X
- Xint kntinit = FALSE;
- X
- X
- Xextern kntdraw(), kntfirst(); /* Defined below. */
- X
- X
- X/* This routine is called by the user command to clear the zee matrix.
- X */
- Xchar *clearzee(str)
- Xchar *str; /* Command line */
- X{
- X int i;
- X kntinfo *knti;
- X
- X knti = &kntprivate;
- X initknt();
- X kntclrzee(knti);
- X
- X if (&kntprivate == ((kntinfo *) gbstore.wprivate)) {
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X knti->perm[i] = -1;
- X }
- X decode(knti->cbuf, knti->pbuf, knti->perm);
- X sprintf(statmsg, GUESSMSG,
- X 0, knti->xindex, knti->yindex, zeecount(knti));
- X gblset(&gblabel, statmsg);
- X wl_draw(&gbstore);
- X }
- X
- X wl_rcursor(&user);
- X return(NULL);
- X}
- X
- X
- X
- X/* This routine is called to set up the guess block window
- X * to be used for guessing the zee matrix.
- X * It can be directly invoked by the command interpreter.
- X * Set up dbstore to show the block after the last block
- X * the the user says to consider complete.
- X */
- Xchar *kntguess(str)
- Xchar *str; /* Command line */
- X{
- X int i;
- X int from,to;
- X gwindow *knt;
- X kntinfo *knti;
- X
- X knt = &gbstore;
- X knti = &kntprivate;
- X initknt();
- X
- X if (!kntinit) {
- X kntinit = TRUE;
- X kntclrzee(knti);
- X }
- X
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X knti->perm[i] = -1;
- X }
- X
- X from = to = 0;
- X if ((i = sscanf(str,"%*[^:]: %d %*[^:]: %d %*[^:]: %d",
- X &from, &to, &knti->min_show)) != 3) {
- X return("Could not parse all arguments.");
- X }
- X else {
- X if (to <= from)
- X return("To: must be less than From:");
- X }
- X
- X dbssetblk(&dbstore, to+1);
- X if (!fillcbuf(to+1, knti->cbuf)) {
- X return("Bad to: value");
- X }
- X decode(knti->cbuf, knti->pbuf, knti->perm);
- X knti->xindex = 0;
- X knti->yindex = 0;
- X knti->lowbnum = from;
- X knti->highbnum = to;
- X
- X gbsswitch(knt,((char *) knti), kntktab, kntfirst, wl_noop, kntdraw);
- X sprintf(statmsg, STARTMSG, from, to, zeecount(knti));
- X gblset(&gblabel, statmsg);
- X kntdraw(knt);
- X
- X wl_setcur(knt, 1, 1);
- X return(NULL);
- X}
- X
- X
- X
- X/* Clear the zee permutation and update any display info.
- X */
- Xkntclrzee(knti)
- Xkntinfo *knti;
- X{
- X int i;
- X
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X knti->zee[i] = -1;
- X knti->zeeinv[i] = -1;
- X }
- X}
- X
- X
- X/* Compute the next successful guess of a wiring of ZEE.
- X * Show it to the user for acceptance/rejection.
- X */
- Xkntnextg(knt)
- Xgwindow *knt;
- X{
- X int guesscnt;
- X kntinfo *knti;
- X knti = ((kntinfo *) knt->wprivate);
- X
- X kntclrlast(knti);
- X while (TRUE) {
- X guesscnt = kntadvance(knti);
- X if ((guesscnt == 0) || (guesscnt >= knti->min_show)) break;
- X kntclrlast(knti);
- X }
- X if (guesscnt == 0) {
- X gblset(&gblabel, "No more guesses");
- X return;
- X }
- X decode(knti->cbuf, knti->pbuf, knti->perm);
- X
- X sprintf(statmsg, GUESSMSG,
- X guesscnt, knti->xindex, knti->yindex, zeecount(knti));
- X gblset(&gblabel, statmsg);
- X kntdraw(knt);
- X}
- X
- X
- X
- X/* Clear last guess in zee, zeeinv, perm.
- X * Note that perm only holds the results of the last guess.
- X */
- Xkntclrlast(knti)
- Xkntinfo *knti;
- X{
- X int tmpv; /* For unpack. */
- X int x,y;
- X int i;
- X
- X while (knti->ustkp > knti->undostk) {
- X unpack(x, y, *(--(knti->ustkp)));
- X knti->zee[x] = -1;
- X knti->zeeinv[y] = -1;
- X }
- X knti->ustkp = knti->savedustkp = knti->undostk;
- X
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X knti->perm[i] = -1;
- X }
- X}
- X
- X
- X
- X/* Advance to the next acceptable guess at a wiring for Zee.
- X * This modifies zee, zeeinv, and perm. Perm only contains the
- X * info derived from this guess, while zee and zeeinv accumulate
- X * information from all preceeding accepted guesses.
- X * Returns the number of guesses that we derived from the initial one.
- X * If out of acceptable guesses, returns 0.
- X * Perm must be cleared before calling this.
- X */
- Xint kntadvance(knti)
- Xkntinfo *knti;
- X{
- X int guesscount;
- X int i;
- X int tmpv; /* For unpack. */
- X int x,y;
- X int tx,ty;
- X int u,v;
- X int tu,tv;
- X int *a2; /* The permutation as in u = A2 x */
- X int *a1; /* The permutation as in v = A1 y */
- X int *propp; /* Temp for undo stack propagation. */
- X int *highperm; /* Perm used to derive next perm. */
- X int trycount; /* Size of trystk. */
- X int *tstkp; /* Stack of guesses to check. */
- X int trystk[BIG];
- X
- X/* kntadvance(knti)
- X */
- X guesscount = 0; /* In case loop body never executes. */
- X
- X if (knti->xindex >= BLOCKSIZE) return(0);
- X if (knti->yindex >= BLOCKSIZE) {
- X knti->yindex = 0;
- X knti->xindex++;
- X }
- X
- X for (x = knti->xindex ; x < BLOCKSIZE ; x++) {
- X if (knti->zee[x] != -1) {
- X knti->yindex = 0;
- X continue;
- X }
- X for (y = knti->yindex ; y < BLOCKSIZE ; y++) {
- X if (knti->zeeinv[y] != -1) continue;
- X guesscount = 0;
- X tstkp = trystk; /* Assume ustkp == undostk. */
- X trycount = 0;
- X *(tstkp++) = pack(x,y);
- X trycount++;
- X
- X while (tstkp > trystk) {
- X unpack(tx, ty, *(--tstkp));
- X trycount--;
- X if (knti->zee[tx] == -1 && knti->zeeinv[ty] == -1) {
- X knti->zee[tx] = ty;
- X knti->zeeinv[ty] = tx;
- X *((knti->ustkp)++) = pack(tx,ty);
- X guesscount++;
- X for (i = knti->lowbnum ; (i+1) <= knti->highbnum ; i++) {
- X a1 = refperm(i);
- X a2 = refperm(i+1);
- X tu = a2[tx];
- X tv = a1[ty];
- X if (tu != -1 && tv != -1 && trycount < BIG) {
- X *(tstkp++) = pack(tu, tv);
- X trycount++;
- X }
- X }
- X }
- X else if (knti->zee[tx] != ty
- X || knti->zeeinv[ty] != tx) { /* If conflict. */
- X while (knti->ustkp > knti->undostk) {
- X unpack(tx, ty, *(--(knti->ustkp)));
- X knti->zee[tx] = -1;
- X knti->zeeinv[ty] = -1;
- X guesscount--;
- X }
- X knti->ustkp = knti->undostk;
- X goto nxtguess;
- X }
- X else continue; /* Already know about it. */
- X }
- X
- X knti->xindex = x; /* Zee[x] = y was a good guess. */
- X knti->yindex = y+1;
- X propp = knti->ustkp;
- X highperm = refperm(knti->highbnum);
- X while (propp > knti->undostk) { /* Update perm. */
- X unpack(tx, ty, *(--propp));
- X v = highperm[ty];
- X if (v != -1 && (tmpv = knti->zeeinv[v]) != -1) {
- X knti->perm[tx] = tmpv;
- X knti->perm[tmpv] = tx;
- X }
- X }
- X return (guesscount);
- X nxtguess: ;
- X }
- X knti->yindex = 0;
- X }
- X
- X knti->yindex = 0;
- X knti->xindex = 0;
- X return(guesscount);
- X}
- X
- X
- X/* Enter our current guess into the decryption block.
- X * Clear out the undo stack.
- X */
- Xkntenter(knt)
- Xgwindow *knt;
- X{
- X kntinfo *knti;
- X
- X knti = ((kntinfo *) knt->wprivate);
- X knti->savedustkp = knti->ustkp; /* If we change our mind. */
- X knti->ustkp = knti->undostk;
- X if (knti->highbnum+1 != dbsgetblk(&dbstore))
- X dbssetblk(&dbstore, knti->highbnum+1);
- X dbsmerge(&dbstore, knti->perm);
- X wl_rcursor(knt);
- X}
- X
- X
- X/* Undo the last guess.
- X */
- Xkntundo(knt)
- Xgwindow *knt;
- X{
- X kntinfo *knti;
- X
- X knti = ((kntinfo *) knt->wprivate);
- X knti->ustkp = knti->savedustkp;
- X kntclrlast();
- X dbsundo(&dbstore);
- X
- X sprintf(statmsg, UNDOMSG, zeecount(knti));
- X gblset(&gblabel, statmsg);
- X wl_rcursor(knt);
- X}
- X
- X
- X/* Behavior when first enter the window.
- X * Put up a help message.
- X * Accept the cursor where it is.
- X */
- Xkntfirst(knt, row, col)
- Xgwindow *knt;
- Xint row,col; /* Current coordinates. */
- X{
- X usrhelp(&user, KNTHELP);
- X wl_setcur(knt, row, col);
- X}
- X
- X
- X
- X/* (re)Draw the window.
- X */
- Xkntdraw(knt)
- Xgwindow *knt;
- X{
- X int i;
- X int row, col; /* Original row and column. */
- X kntinfo *knti;
- X
- X knti = ((kntinfo *) knt->wprivate);
- X row = knt->wcur_row;
- X col = knt->wcur_col;
- X
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X if (i%LINELEN == 0) {
- X wl_setcur(knt, gbspos2row(i), gbspos2col(i));
- X }
- X plnchars(1, char2sym(knti->pbuf[i]));
- X }
- X
- X for (i = gbspos2row(BLOCKSIZE) ; i <= GBHEIGHT ; i++) {
- X wl_setcur(knt, i, 1);
- X plnchars(LINELEN, ' ');
- X }
- X
- X for (i = 1 ; i <= GBHEIGHT ; i++) {
- X wl_setcur(knt, i, LINELEN+1);
- X plnchars(knt->wwidth - LINELEN, ' ');
- X }
- X
- X wl_setcur(knt, row, col);
- X}
- X
- X
- X/* Return number of known wires in Zee.
- X * Max is 256.
- X */
- Xint zeecount(knti)
- Xkntinfo *knti;
- X{
- X return(permcount(knti->zee));
- X}
- X
- X
- X/* Store Zee permutation on a file.
- X */
- Xstorezee(fd)
- XFILE *fd;
- X{
- X writeperm(fd, kzee);
- X}
- X
- X
- X/* Load the Zee permutation from a file.
- X * Update display if necessary.
- X */
- Xloadzee(fd)
- XFILE *fd;
- X{
- X int i;
- X kntinfo *knti;
- X
- X knti = &kntprivate;
- X initknt();
- X kntinit = TRUE;
- X kntclrzee(knti); /* Clear zeeinv */
- X
- X readperm(fd, kzee);
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X if (kzee[i] != -1) {kzeeinv[kzee[i]] = i;}
- X }
- X
- X if (knti == ((kntinfo *) gbstore.wprivate)) {
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X knti->perm[i] = -1;
- X }
- X decode(knti->cbuf, knti->pbuf, knti->perm);
- X sprintf(statmsg, GUESSMSG,
- X 0, knti->xindex, knti->yindex, zeecount(knti));
- X gblset(&gblabel, statmsg);
- X wl_draw(&gbstore);
- X wl_setcur(&gbstore, 1, 1);
- X }
- X}
- X
- X
- X/* Set up all the pointers in kntprivate.
- X */
- Xinitknt()
- X{
- X int i;
- X gwindow *knt;
- X kntinfo *knti;
- X
- X knt = &gbstore;
- X knti = &kntprivate;
- X
- X knti->zee = kzee;
- X knti->zeeinv = kzeeinv;
- X
- X knti->cbuf = gcbuf;
- X knti->pbuf = gpbuf;
- X knti->perm = gperm;
- X
- X knti->undostk = kustk;
- X knti->ustkp = knti->savedustkp = knti->undostk;
- X}
- END_OF_knit.c
- if test 10707 -ne `wc -c <knit.c`; then
- echo shar: \"knit.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f zeecode.perm -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"zeecode.perm\"
- else
- echo shar: Extracting \"zeecode.perm\" \(11550 characters\)
- sed "s/^X//" >zeecode.perm <<'END_OF_zeecode.perm'
- X 28 146 116 150 159 64 172 249 200 232
- X 90 149 63 239 238 95 49 254 143 8
- X191 231 123 117 243 210 179 186 119 17
- X107 46 174 203 21 12 97 53 135 71
- X 52 78 204 31 220 77 211 24 225 121
- X 74 228 202 171 11 81 67 69 141 213
- X 66 94 195 217 29 154 3 15 59 76
- X205 155 25 93 209 160 212 36 173 68
- X221 193 176 196 4 138 99 222 70 57
- X 7 252 41 43 62 79 48 61 145 38
- X 20 216 166 208 40 187 0 153 5 137
- X 55 130 241 6 207 128 227 190 142 125
- X177 75 226 105 2 175 51 120 96 13
- X139 47 127 246 248 18 44 16 136 167
- X132 113 151 98 244 114 182 198 201 189
- X144 22 140 122 109 83 131 180 253 58
- X162 50 250 134 37 1 35 242 23 214
- X194 112 157 223 165 233 156 161 188 104
- X124 103 54 234 89 80 101 26 19 85
- X192 147 181 65 199 9 247 245 129 60
- X169 102 32 88 224 106 235 45 236 84
- X255 92 178 215 230 33 115 185 27 39
- X237 251 30 14 163 126 219 87 206 73
- X158 56 110 168 91 152 197 108 133 148
- X 72 118 184 240 100 164 111 170 183 229
- X 42 10 218 82 86 34
- X 96 114 124 223 97 19 10 13 43 44
- X 6 38 231 7 200 207 179 134 133 5
- X100 230 48 160 152 93 162 168 191 127
- X 65 103 183 90 252 193 243 242 11 180
- X 87 173 154 8 9 99 112 58 22 108
- X199 95 77 66 163 62 128 190 47 79
- X215 109 55 245 73 30 53 178 214 82
- X201 138 206 64 240 182 228 52 140 59
- X197 248 69 203 175 111 137 40 153 139
- X 33 195 212 25 217 51 0 4 251 45
- X 20 122 148 31 227 234 167 202 49 61
- X219 85 46 246 1 135 142 254 211 249
- X144 255 101 218 2 150 186 29 56 169
- X185 247 164 18 17 115 250 86 71 89
- X 78 205 116 222 120 216 226 158 102 189
- X125 225 24 88 42 159 221 188 147 155
- X 23 210 26 54 132 232 184 106 27 129
- X236 196 253 41 204 84 238 235 67 16
- X 39 192 75 32 166 130 126 224 157 149
- X 57 28 181 35 241 91 171 80 208 50
- X 14 70 107 83 174 141 72 15 198 233
- X161 118 92 244 68 60 145 94 123 110
- X237 156 143 3 187 151 146 104 76 239
- X 21 12 165 209 105 177 170 220 176 229
- X 74 194 37 36 213 63 113 131 81 119
- X136 98 34 172 117 121
- X 20 122 118 119 71 229 158 28 223 174
- X215 -1 197 249 82 126 237 23 87 93
- X 0 35 252 17 77 177 137 225 7 163
- X 52 171 42 155 214 21 84 60 216 85
- X 45 152 32 181 220 40 241 235 142 210
- X243 69 30 83 99 134 212 253 70 144
- X 37 63 234 61 132 250 173 114 95 51
- X 58 4 73 72 175 168 211 24 92 169
- X176 166 14 53 36 39 207 18 148 117
- X129 255 78 19 110 68 151 154 101 54
- X244 98 242 147 227 204 128 203 188 254
- X 94 217 170 251 67 231 -1 89 2 3
- X206 146 1 183 -1 209 15 150 106 90
- X184 159 64 141 55 238 195 26 162 205
- X245 133 48 221 59 165 121 103 88 -1
- X127 96 41 186 97 33 196 -1 6 131
- X187 194 138 29 167 145 81 164 75 79
- X112 31 178 66 9 74 80 25 172 -1
- X -1 43 224 123 130 236 153 160 108 246
- X192 230 190 222 161 136 156 12 200 213
- X198 239 248 107 105 139 120 86 247 125
- X 49 76 56 199 34 10 38 111 233 -1
- X 44 143 193 8 182 27 232 104 240 5
- X191 115 226 218 62 47 185 16 135 201
- X228 46 102 50 100 140 189 208 202 13
- X 65 113 22 57 109 91
- X 90 49 26 132 156 140 212 129 147 122
- X198 -1 97 148 38 79 25 154 80 173
- X214 216 248 184 161 16 2 107 66 168
- X 33 112 195 30 166 236 65 155 14 84
- X222 211 123 53 136 47 69 45 218 1
- X125 243 134 43 -1 102 145 126 238 194
- X 78 232 138 246 224 36 28 225 150 46
- X130 215 120 188 119 105 231 209 60 15
- X 18 87 185 176 39 160 182 81 159 158
- X 0 151 235 192 183 200 118 12 174 -1
- X106 -1 55 196 207 75 100 27 249 187
- X163 242 31 230 254 205 179 190 96 74
- X 72 233 9 42 241 50 57 228 142 7
- X 70 206 3 149 52 227 44 220 62 245
- X 5 221 128 186 244 56 204 8 13 133
- X 68 91 197 165 17 37 4 180 89 88
- X 85 24 193 110 199 153 34 201 29 255
- X177 247 226 19 98 252 83 170 237 116
- X157 191 86 94 23 82 143 109 73 219
- X117 181 93 162 59 32 103 152 10 164
- X 95 167 250 239 146 115 131 104 217 77
- X234 41 6 251 20 71 21 208 48 189
- X137 141 40 253 64 67 172 135 127 240
- X113 76 61 121 210 92 35 178 58 203
- X229 124 111 51 144 139 63 171 22 108
- X202 213 175 223 114 169
- X 60 42 26 79 203 204 122 237 15 97
- X106 238 133 33 159 8 165 145 27 191
- X192 69 250 117 126 183 2 18 50 65
- X218 57 143 13 101 36 35 93 116 213
- X163 199 1 171 109 74 92 177 56 175
- X 28 132 162 196 -1 227 48 31 80 221
- X 0 248 202 103 233 29 140 95 170 21
- X216 164 137 190 45 189 113 193 188 3
- X 58 160 155 181 176 94 186 104 111 225
- X198 125 46 37 85 67 252 9 231 223
- X169 34 255 63 87 154 10 174 152 44
- X201 88 -1 76 179 118 38 23 115 161
- X247 123 6 121 187 91 24 240 241 239
- X197 207 51 12 151 185 138 72 136 148
- X 66 214 234 32 150 17 254 -1 139 226
- X144 134 108 195 105 82 228 172 173 14
- X 81 119 52 40 71 16 208 246 242 100
- X 68 43 157 158 107 49 84 47 229 114
- X -1 83 -1 25 230 135 86 124 78 75
- X 73 19 20 77 245 153 53 130 90 41
- X210 110 62 4 5 244 211 131 166 219
- X200 206 220 39 141 222 70 253 30 209
- X212 59 215 99 232 89 149 55 156 178
- X184 98 224 64 142 236 235 7 11 129
- X127 128 168 249 205 194 167 120 61 243
- X 22 -1 96 217 146 102
- X161 17 99 150 223 175 172 24 25 204
- X147 122 181 198 54 56 125 1 202 67
- X188 143 49 168 7 8 145 254 177 98
- X 32 211 30 84 57 238 195 83 217 245
- X160 178 108 89 76 81 228 225 184 22
- X207 176 94 93 14 75 15 34 169 219
- X152 189 107 158 193 123 95 19 80 141
- X144 253 248 164 226 55 44 166 230 247
- X 68 45 209 37 33 138 -1 213 101 43
- X220 128 194 53 52 66 231 134 29 2
- X190 88 103 102 224 180 199 62 42 240
- X116 236 115 153 156 112 110 229 183 234
- X131 149 11 65 187 16 140 196 91 215
- X239 120 243 139 97 218 154 174 85 133
- X126 69 163 21 70 26 182 10 232 121
- X 3 162 60 113 136 192 114 171 63 185
- X 40 0 151 142 73 250 77 233 23 58
- X197 157 6 -1 137 5 51 28 41 227
- X105 12 146 118 48 159 255 124 20 61
- X100 -1 155 64 92 36 127 170 13 106
- X244 210 18 246 9 251 208 50 206 82
- X201 31 249 87 242 129 241 38 135 59
- X 90 -1 252 4 104 47 74 179 46 117
- X 78 96 148 167 119 237 111 235 35 130
- X109 216 214 132 200 39 203 79 72 212
- X165 205 222 71 27 186
- X120 146 232 66 217 81 113 76 144 239
- X 44 49 230 111 166 60 151 218 34 72
- X 80 128 193 249 140 148 116 210 183 165
- X 94 51 109 133 18 192 163 73 252 158
- X 61 214 195 46 10 102 43 90 131 11
- X122 31 135 172 153 207 188 58 57 227
- X 15 40 77 99 143 138 3 231 226 136
- X221 190 19 37 253 104 7 62 254 185
- X 20 5 126 132 173 189 124 91 150 255
- X 47 87 212 184 30 196 242 149 187 63
- X178 112 45 228 75 180 177 141 125 32
- X121 13 101 6 161 234 26 244 224 137
- X 0 110 50 157 86 108 82 156 21 147
- X238 48 83 33 240 52 69 119 65 175
- X 24 107 160 64 8 176 1 129 25 97
- X 88 16 225 54 243 164 127 123 39 200
- X142 114 174 36 155 29 14 169 233 167
- X211 216 53 84 162 139 145 106 100 204
- X105 201 223 28 93 79 203 98 56 85
- X 71 251 35 22 205 42 95 219 213 235
- X159 181 222 186 179 194 220 55 246 215
- X 27 170 92 198 41 209 171 4 17 197
- X206 70 202 182 118 152 68 59 103 245
- X 12 67 2 168 115 199 247 250 130 9
- X134 248 96 154 117 229 208 236 241 23
- X237 191 38 74 78 89
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
- X -1 -1 -1 -1 -1 -1
- END_OF_zeecode.perm
- if test 11550 -ne `wc -c <zeecode.perm`; then
- echo shar: \"zeecode.perm\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 5 \(of 11\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-